/*
 *    This file is part of BlobDB.
 *
 *    BlobDB is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    BlobDB is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with BlobDB.  If not, see <http://www.gnu.org/licenses/>.
 *    
 *    Copyright(c) 2011 Michael Kankkonen
 *    http://www.vnetcon.org
 */


package org.vnetcon.blobdb.database.util;

import org.vnetcon.blobdb.database.SQLException;
import org.vnetcon.blobdb.database.Statement;

public class TableRow extends InfoBase {

	
	public static final int ROWID_SIZE = 24;
	
	byte row[] = null;
	int ROWSIZE_MAX = -1;
	
	int tableID = -1;
	int tableDataID = -1;
	int rowID = -1;
	int updateDate = -1;
	int updateTime = -1;
	int updateTimeMills = -1;

	public TableRow(byte rowdata[]) throws SQLException {
		this.row = rowdata;
	}	
	
	public TableRow(byte rowdata[], int ROWSIZE_MAX) throws SQLException {
		this.row = rowdata;
		this.ROWSIZE_MAX = ROWSIZE_MAX;
		if(this.row.length - ROWID_SIZE != this.ROWSIZE_MAX){
			throw new SQLException("Rowdata byte array must be " + this.ROWSIZE_MAX + " bytes");
		}
	}
	
	public void initColumn(int iType, int iStart, int iLength) throws SQLException {
		int i = iStart + ROWID_SIZE;
		int iEnd = i + iLength;
		
		if(iType == ColumnInfo.CHAR || iType == ColumnInfo.DATE || iType == ColumnInfo.TIME || iType == ColumnInfo.FOREIGN_KEY){
			while(i < iEnd){
				row[i] = 0;
				i++;
			}
		}

		if(iType == ColumnInfo.NUMBER || iType == ColumnInfo.DECIMAL){
			while(i < iEnd){
				row[i] = '0';
				i++;
			}
		}
		
	}

	public byte[] getColBytes(int iStart, int iLength) throws SQLException {
		byte ret[] = null;
		int i = 0;
		iStart = iStart + ROWID_SIZE;
		int iRetSize = 0;
		
		while(i < iLength){
			if(row[iStart + i] == 0){
				break;
			}
			iRetSize++;
			i++;
		}

		ret = new byte[iRetSize];

		i = 0;
		while(i < iRetSize){
			ret[i] = row[iStart + i];
			i++;
		}

		return ret;
	}
	
	public void writeValue(int iType, int iStart, int iColLength, int iDecimals, byte[] value) throws SQLException {
		String buf = new String(value);
		if(value.length > iColLength){
			throw new SQLException("Value too large for column: " + buf);
		}

		if(iType == ColumnInfo.NUMBER){
			try{
				Long.parseLong(buf);
			}catch(Exception ex){
				throw new SQLException("Invalid number: " + buf);
			}
		}

		if(iType == ColumnInfo.DECIMAL){
			
			try{
				String parts[] = buf.split("\\.");
				if(parts.length != 2){
					throw new Exception();
				}
				
				if(parts[1].length() != iDecimals){
					throw new Exception();
				}
				
			}catch(Exception ex){
				throw new SQLException("Invalid count decimals. Expecting: " + iDecimals);
			}
			
			try{
				Double.parseDouble(buf);
			}catch(Exception ex){
				throw new SQLException("Invalid decimal: " + buf);
			}
		}

		if(iType == ColumnInfo.DATE){
			if(value.length != 8){
				throw new SQLException("Invalid length in date: " + buf);
			}
			try{
				Integer.parseInt(buf);
			}catch(Exception ex){
				throw new SQLException("Invalid date value: " + buf);
			}
		}
		
		if(iType == ColumnInfo.TIME){
			if(value.length != 6){
				throw new SQLException("Invalid length in time: " + buf);
			}
			try{
				Integer.parseInt(buf);
			}catch(Exception ex){
				throw new SQLException("Invalid time value: " + buf);
			}
		}
		
		initColumn(iType, iStart, iColLength);
		iStart = iStart + ROWID_SIZE;
		
		if(iType == ColumnInfo.NUMBER || iType == ColumnInfo.DECIMAL){
			int ii = 0;
			int i = iStart + iColLength - value.length;
			int iEnd = iStart + iColLength;
			while(i < iEnd){
				row[i] = value[ii];
				i++;
				ii++;
			}
		}

		if(iType == ColumnInfo.CHAR || iType == ColumnInfo.DATE || iType == ColumnInfo.TIME || iType == ColumnInfo.FOREIGN_KEY){
			int i = iStart;
			int ii = 0;
			int iEnd = iStart + value.length;
			while(i < iEnd){
				row[i] = value[ii];
				i++;
				ii++;
			}
			
		}
		
	}

	public int getTableID() {
		this.tableID = this.readInt(row, 0);
		return tableID;
	}

	public void setTableID(int tableID) throws Exception {
		this.writeInt(row, 0, tableID);
		this.tableID = tableID;
	}

	public int getTableDataID() {
		this.tableDataID = this.readInt(row, 4);
		return tableDataID;
	}

	public void setTableDataID(int tableDataID) throws Exception {
		this.writeInt(row, 4, tableDataID);
		this.tableDataID = tableDataID;
	}

	public int getRowID() {
		this.rowID = this.readInt(row, 8);
		return rowID;
	}

	public void setRowID(int rowID) throws Exception {
		this.writeInt(row, 8, rowID);
		this.rowID = rowID;
	}

	public int getUpdateDate() {
		return updateDate;
	}

	public void setUpdateDate(int updateDate) throws Exception {
		this.writeInt(this.row, 12, updateDate);
		this.updateDate = updateDate;
	}

	public int getUpdateTime() {
		return updateTime;
	}

	public void setUpdateTime(int updateTime) throws Exception {
		this.writeInt(this.row, 16, updateTime);
		this.updateTime = updateTime;
	}

	public int getUpdateTimeMills() {
		return updateTimeMills;
	}

	public void setUpdateTimeMills(int updateTimeMills) throws Exception {
		this.writeInt(this.row, 20, updateTimeMills);
		this.updateTimeMills = updateTimeMills;
	}

	public String getRowIDString(){
		String strRet = "1.1.1.1";
		return strRet;
	}
	
}
